package org.rectask.model;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * A recurrent task.
 * 
 * @author sergut
 *
 */
public class Task {
    /**
     * The name of a task
     */
    String name;
    
    /**
     * Date of start. 
     * 
     * The task is executed for the first time on this day. 
     */
    Date startDate;
    
    /**
     * Minimum periodicity (m).
     * 
     * The task should be executed m days after the last execution, 
     * not before. 
     */
    int minPeriod;
    
    /**
     * Maximum periodicity (M).
     * 
     * The task should be executed M days after the last execution, 
     * no later. 
     */
    int maxPeriod;
    
    /**
     * Day in which the task has been executed.
     */
    SortedDateList executionDates;
    
    /**
     * A new task, defined by its starting date, its minimum 
     * periodicity and a maximum periodicity. 
     */
    public Task(String name, Date startDate, int minPeriod, int maxPeriod) {
	if (minPeriod > maxPeriod)
	    throw new IllegalArgumentException("Min period greater than max period");
	
	this.name      = name;
	this.startDate = startDate;
	this.minPeriod = minPeriod;
	this.maxPeriod = maxPeriod;
	executionDates = new SortedDateList();
    }
  
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
	this.name = name;
    }

    /**
     * @return the startDate
     */
    public Date getStartDate() {
        return startDate;
    }

    /**
     * @return the minPeriod
     */
    public int getMinPeriod() {
        return minPeriod;
    }

    /**
     * @param minPeriod the minPeriod to set
     */
    public void setMinPeriod(int minPeriod) {
        this.minPeriod = minPeriod;
    }

    /**
     * @return the maxPeriod
     */
    public int getMaxPeriod() {
        return maxPeriod;
    }

    /**
     * @param maxPeriod the maxPeriod to set
     */
    public void setMaxPeriod(int maxPeriod) {
        this.maxPeriod = maxPeriod;
    }

    /**
     * Returns the list of execution dates.
     * 
     * @return the executionDates
     */
    public ArrayList<Date> getExecutionDates() {
        return executionDates.getDates();
    }

    /**
     * Adds a date to the list of execution dates.
     * 
     */
    public void addExecutionDate(Date date) {
	executionDates.add(date);
    }
    
    /**
     * Removes a date from the list of execution dates.
     * 
     */
    public void removeExecutionDate(Date date) {
	executionDates.add(date);
    }
    
    /**
     * Adds another date to the list of execution dates, if 
     * it is not there. If it is, it removes it. 
     * 
     */
    public void toggleExecutionDate(Date date) {
	executionDates.toggle(date);
    }
    
    /**
     * 
     */
    public Date getLastExecutionDateBefore(Date date) {
	return executionDates.getLastDateBefore(date);
    }
    
    /**
     * Converts this task to an XML representation. 
     * 
     * @return the XML representation of this task.
     */
    public String toXML() {
	String result = new String();
	result += "<task>";
	result += "<name>" + this.getName() + "</name>";
	result += "<start-date>" + this.startDate.toString() + "</start-date>";
	result += "<min-period>" + this.minPeriod + "</min-period>";
	result += "<max-period>" + this.maxPeriod + "</max-period>";
	result += "<execution-dates>";
	for (Iterator<Date> itr = this.executionDates.iterator(); itr.hasNext();) {
	    result += "<date>" + itr.next().toString() + "</date>";
	}
	result += "</execution-dates>";
	result += "</task>";
	return result;
    }
    
    /**
     * Returns true if the other object is a Task, and has the same
     * name as this task. 
     */
    public boolean equals(Object o) {
	if (o instanceof Task) {
	    Task otherTask = (Task) o;
	    if (otherTask.getName().equals(this.getName()))
		return true;
	}
	return false;
    }

    /**
     * Returns the hashcode of this task
     */
    public int hashCode() {
	return this.getName().hashCode() + 1;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
	// TODO Auto-generated method stub

    }
}
